home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Macintosh Sample Code / SC.016.OffSample / UFailure.a < prev    next >
Encoding:
Text File  |  1988-10-31  |  11.8 KB  |  392 lines  |  [TEXT/MPS ]

  1. ;
  2. ;    Apple Macintosh Developer Technical Support
  3. ;
  4. ;    Exception handling for MPW Pascal, MacApp and MPW C
  5. ;
  6. ;    UFailure (aka Signals) - “Exceptional code, with a few exceptions.”
  7. ;
  8. ;    UFailure.a    -    Assembly Source
  9. ;
  10. ;    Copyright © 1985-1988 Apple Computer, Inc.
  11. ;    All rights reserved.
  12. ;
  13. ;    Versions:    1.0                    11/88
  14. ;
  15. ;    Components:    UFailure.p            November 1, 1988
  16. ;                UFailure.h            November 1, 1988
  17. ;                UFailure.inc1.p        November 1, 1988
  18. ;                UFailure.a            November 1, 1988
  19. ;                TestCignal.c        November 1, 1988
  20. ;                TestCignal.make        November 1, 1988
  21. ;                TestSignal.p        November 1, 1988
  22. ;                TestSignal.make        November 1, 1988
  23. ;
  24. ;    UFailure (or Signals) is a set of exception handling routines suitable for
  25. ;    use with MacApp, MPW C, and MPW Pascal. It is a jazzed-up version of the MacApp
  26. ;    UFailure unit. There is a set of C interfaces to it as well.
  27. ;
  28.  
  29.             PRINT    OFF
  30.             INCLUDE    'Traps.a'
  31.             PRINT    ON
  32.             
  33.             STRING    ASIS
  34.  
  35. ;=============================================================================================
  36.             GblA    &UsingMacApp
  37.     If        &TYPE('&Debugging') = 'UNDEFINED' Then
  38.             GblA    &Debugging
  39. &UsingMacApp    SetA    0            ; we assume we’re MacAppless if &Debugging isn’t defined 
  40.         If        &TYPE('&Debug') = 'UNDEFINED' Then
  41. &Debugging    SetA    0            ; default to debugging off
  42.         Else
  43. &Debugging    SetA    &Debug        ; use the makefile definition of &Debug
  44.         EndIf
  45.     Else    
  46. &UsingMacApp    SetA    1            ; we assume we have MA if &Debugging is defined 
  47.     EndIf
  48. ;=============================================================================================
  49.     If        &TYPE('Head') = 'UNDEFINED' Then
  50.         Macro    
  51.         Head
  52.                 GblA    &Debugging
  53.             If  &Debugging Then
  54.                 Link    A6,#0        ; These two instructions form a slow no-op
  55.                 Move.L    (SP)+,A6
  56.             EndIf
  57.         EndM
  58.     EndIf
  59. ;=============================================================================================
  60.     If        &TYPE('Tail') = 'UNDEFINED' Then
  61.         Macro    
  62.         Tail
  63.                 GblA    &Debugging
  64.             If  &Debugging Then
  65.                 Unlk    A6
  66.                 Rts
  67.                 DC.B    &Ord(&SubStr(&Syslst[1],2,1)) + $80
  68.                 DC.B    '&SubStr(&Syslst[1],3,7)'
  69.             EndIf
  70.         EndM
  71.     EndIf
  72. ;=============================================================================================
  73.         
  74. ; the following constant sets the limit on the depth of nested CatchSignals
  75. SigBlockSize EQU    8                            ;number of elements in block
  76.  
  77. CatchSigErr    EQU        200                            ;"insufficient heap" message
  78. SigElSize    EQU        72                            ;byte size of FailInfo record
  79. FrameRet    EQU        4                            ;return addr. for frame (off A6)
  80. SigBigA6    EQU        $FFFFFFFF                    ;A6 at outer level (for Pascal)
  81. nSavedRegs    EQU     11                            ;number of registers saved in FailInfo record
  82.  
  83. ; offsets into the FailInfo record (see UFailure.p)
  84. SigA6        EQU        36
  85. SigSP        EQU        40
  86. SigCode        EQU        44
  87. SigMessage    EQU        46
  88. SigFailA6    EQU        50
  89. SigFailPC    EQU        54
  90. whatSignals    EQU        66
  91. SigFRet        EQU        68
  92.  
  93.     
  94. ; The global data used by these routines follows. It is in the form of a 
  95. ; RECORD, but, unlike above, no origin is specified, which means that memory 
  96. ; space *will* be allocated.
  97. ; This data is referenced through a WITH statement at the beginning of the 
  98. ; procs that need to get at this data. Since the Assembler knows when it is 
  99. ; referencing data in a data module (since they must be declared before they 
  100. ; are accessed), and since such data can only be accessed based on A5, there 
  101. ; is no need to explicitly specify A5 in any code which references the data 
  102. ; (unless indexing is used).  Thus, in this program we have omitted all A5 
  103. ; references when referencing the data.
  104.  
  105. SigGlobals RECORD        ;no origin means this is a data record
  106.                         ;not a template(as above)
  107. SigEnd        DS.L    1    ;current end of table
  108. SigNow        DS.L    1    ;the current offset
  109. SigPointer    DC.L    0    ;the handle := 0 initially
  110.             ENDR    
  111.  
  112.  
  113.         If  &UsingMacApp Then
  114.             Seg     'MAInit'
  115.         EndIf
  116. InitSignals    PROC    EXPORT                        ;PROCEDURE InitSignals;
  117.             EXPORT    InitUFailure
  118.             IMPORT    gTopHandler:Data
  119.             IMPORT    gInitHandler:Data
  120.         If  &UsingMacApp And &Debugging Then
  121.             IMPORT    gAskAboutAlloc:Data
  122.             IMPORT    gAskFailure:Data
  123.         EndIf
  124.             WITH    SigGlobals
  125. ;the above statement makes the template SigElement and the global data 
  126. ;record SigGlobals available to this procedure
  127.  
  128.              Head
  129.             MOVE.L    #SigBigA6,A6                ;make A6 valid for Signal
  130. InitUFailure                                    ;PROCEDURE InitUFailure;
  131.             CLR.L    gTopHandler(A5)                ;nothing in the list
  132.             CLR.L    gInitHandler(A5)            ;MA has another list during initialization
  133.         If  &UsingMacApp And &Debugging Then
  134.             CLR.B    gAskAboutAlloc(A5)            ;set the MA debugging guys to FALSE
  135.             CLR.B    gAskFailure(A5)
  136.         EndIf
  137.  
  138.             MOVE.L    #SigBlockSize*SigElSize,D0
  139.             _NewPtr                                ;try to get a table
  140.             BNE.S    forgetit                    ;we couldn't get that!?
  141.             
  142.             MOVE.L    A0,SigPointer                ;save it
  143.             MOVE.L    #-SigElSize,SigNow            ;point "now" before start
  144.             MOVE.L    #SigBlockSize*SigElSize,SigEnd ;save the end
  145. forgetit    RTS
  146.         
  147.             Tail    'INITUFAI'
  148.             ENDP
  149.  
  150.  
  151.         If  &UsingMacApp Then
  152.             Seg     'MAMain'
  153.         EndIf
  154. CatchCFailures PROC    EXPORT                        ;pascal void CatchCFailures(FailInfo &fi, HandlerFuncPtr handler);
  155.             IMPORT    FailCEntry
  156.             
  157.             Head
  158.             MOVE.L    (A7)+,D2                    ;save return address
  159.             MOVEQ    #0,D1                        ;CatchCFailures used  (no A6 link, uses handler proc.)
  160.             BRA.S    FailCEntry                    ;finish from CatchFailures
  161.             Tail    'CATCHCFA'
  162.  
  163. CatchFailures PROC    EXPORT                        ;PROCEDURE CatchFailures(VAR fi: FailInfo;
  164. ;                                                    PROCEDURE Handler(code: INTEGER; message: LONGINT));
  165.             IMPORT    FailuresEntry
  166.             EXPORT    FailCEntry
  167.             WITH    SigGlobals
  168.             
  169.             Head
  170.             MOVE.L    (A7)+,D2                    ;save return address
  171.             ADDQ    #4,A7                        ;discard A6 link
  172.             MOVEQ    #-1,D1                        ;CatchFailures used  (maybe A6 link???, handler proc.)
  173. FailCEntry
  174.             MOVE.L    (A7)+,A1                    ;get handler address
  175.             MOVE.L    (A7)+,A0                    ;FailInfo record address
  176.             BRA.S    FailuresEntry                ;enter CatchSignal with D2, A0, A1 set
  177.             Tail    'CATCHFAI'
  178.  
  179. CatchSignal    PROC    EXPORT                        ;FUNCTION CatchSignal:INTEGER
  180.             IMPORT    SiggyPop2,Signal,SigDeath
  181.             IMPORT    gTopHandler:Data
  182.             EXPORT    FailuresEntry
  183.             WITH    SigGlobals
  184.             
  185.             Head
  186.             MOVE.L    (A7)+,A1                    ;grab return address for “handler” address
  187.             MOVE.L    A1,D2                        ;save return address
  188.             MOVEQ    #1,D1                        ;CatchSignals used; no A6 link needed on stack, no proc.
  189.             CLR.W    (A7)                        ;no error code (before its time)
  190.  
  191.             MOVE.L    SigPointer,D0                ;point to table
  192.             BEQ        SigDeath
  193.             MOVE.L    D0,A0
  194.             MOVE.L    SigNow,D0
  195.             ADD.L    #SigElSize,D0
  196.             MOVE.L    D0,SigNow                    ;save new position
  197.             CMP.L    SigEnd,D0                    ;have we reached the end?
  198.             BNE.S    catchit                        ;no, proceed
  199.             
  200. ;signals, we use 'em ourselves
  201.             MOVE.L    SigNow,SigEnd                ;restore old ending offset
  202.             MOVE.L    #SigElSize,D0
  203.             SUB.L    D0,SigNow                    ;ditto for current position
  204.             MOVE.W    #CatchSigErr,4(A7)            ;we'll signal a "couldn't
  205.                                                 ;  catch" error
  206.             JSR        Signal                        ;never returns of course
  207.                     
  208. catchit        
  209.             ADD.L    D0,A0                        ;point to new entry
  210. FailuresEntry                                    ;A0=pointer to FailInfo block,A1=handler address,
  211.                                                 ; D1=flag showing how we entered, D2=return address
  212.             MOVE.L    A0,D0                        ;save FailInfo record address
  213.  
  214.             MOVE.W    D1,whatSignals(A0)            ;remember what’s catching (-1=CatchFailures,
  215.                                                 ; 0=CatchCFailures, 1=CatchSignal)
  216.             BLE.S    @1                            ;can’t use frame to clean up if they’ll call Success
  217.  
  218.             CMP.L    #SigBigA6,A6                ;are we at the outer level?
  219.             BEQ.S    @1                            ;yes, no frame, no cleanup needed 
  220.             MOVE.L    FrameRet(A6),SigFRet(A0)    ;save old frame return
  221.                                                 ; address
  222.             LEA        SiggyPop,A0
  223.             MOVE.L    A0,FrameRet(A6)                ;set cleanup code address
  224.             MOVE.L    D0,A0                        ;restore FailInfo record address
  225. @1        
  226.             MOVEM.L A2-A7/D3-D7,(A0)            ;save all registers first (note that the saved
  227.                                                 ; stack points to the function result for CatchSignal)
  228.             ADD     #nSavedRegs*4,A0            ;advance pointer by # bytes regs
  229.         
  230.             CLR.W    (A0)+                        ;clear error field
  231.             CLR.L    (A0)+                        ;clear message field
  232.             CLR.L    (A0)+                        ;clear A6 link
  233.             
  234.             TST.W    D1                            ;was CatchFailures used?
  235.             BPL.S    @2                            ;no, CatchCFailures or CatchSignal; skip
  236.             MOVE.L    A6,-4(A0)                    ;save the A6Link
  237. @2
  238.             MOVE.L    A1,(A0)+                    ;save the handler ptr
  239.         
  240.             MOVE.L    gTopHandler(A5),(A0)+        ;Link the FailInfo into the list
  241.             MOVE.L    D0,gTopHandler(A5)
  242.             MOVE.L    D2,(A0)+                    ;remember the caller's PC for MA debugging
  243.  
  244.             MOVE.L    D2,A0                        ;get return address
  245.             JMP        (A0)
  246.             Tail    'CATCHSIG'
  247.  
  248.             ALIGN
  249. SiggyPop
  250.             Head
  251.             MOVE.L    D0,-(A7)                    ;save D0 in case we’re returning from a c function
  252.  
  253.             MOVE.L    SigPointer,A0
  254.             MOVE.L    A0,D0                        ;to set CCR
  255.             BEQ        SigDeath                    ;nil pointer means trouble
  256.             MOVE.L    SigNow,D0                    ;grab table offset to entry
  257.             BMI        SigDeath                    ;if no entries then give up
  258.             ADD.L    D0,A0                        ;point to current element
  259.             
  260.             MOVE.L    SigFRet(A0),-(A7)            ;push proc's real return address
  261.             BSR        SiggyPop2                    ;pop element and call Success to pop handler
  262.             MOVE.L    (A7)+,A1                    ;get proc’s return address
  263.             MOVE.L    (A7)+,D0                    ;get back D0 in case we’re returning from c
  264.             JMP        (A1)
  265.             Tail    'SIGGYPOP'
  266.             
  267.             ENDP
  268.  
  269.  
  270.  
  271.  
  272.         If  &UsingMacApp Then
  273.             Seg     'MAMain'
  274.         EndIf
  275. FreeSignal    PROC    EXPORT                        ;PROCEDURE FreeSignal;
  276.             IMPORT    SigDeath,Success
  277.             IMPORT    gTopHandler:Data
  278.             EXPORT    SiggyPop2
  279.             WITH    SigGlobals
  280.             
  281.             Head
  282.             MOVE.L    gTopHandler(A5),A0            ;point to FailInfo record
  283.             MOVE.L    A0,D0                        ;to set CCR
  284.             BEQ.S    SigDeath
  285.             
  286.             TST.W    whatSignals(A0)                ;was CatchSignal used?
  287.             BLE.S    SiggyPop3                    ;no, call Success and return
  288.             
  289.             MOVE.L    SigNow,D0                    ;grab table offset to entry
  290.             
  291.             MOVE.L    SigA6(A0),A1                ;get A6 at point of CatchSignal
  292.             CMP.L    #SigBigA6,A1                ;is it at the outer level?
  293.             BEQ.S    SiggyPop2                    ;yes, don't jam the address if no frame 
  294.             MOVE.L    SigFRet(A0),FrameRet(A1)    ;"pop" cleanup code
  295. SiggyPop2
  296.             SUB.L    #SigElSize,D0
  297.             MOVE.L    D0,SigNow                    ;"pop" the entry
  298. SiggyPop3
  299.             MOVE.L    A0,-(A7)                    ;push address for Success (FailInfo’s)
  300.             JSR        Success                        ;let MacApp remove FailInfo from list; return
  301.             RTS
  302.             Tail    'FREESIGN'
  303.             
  304.             ENDP
  305.  
  306.         If  &UsingMacApp Then
  307.             Seg     'MAMain'
  308.         EndIf
  309. SignalMessage PROC    EXPORT                        ;PROCEDURE SignalMessage(code: INTEGER; message: LONGINT);
  310.             IMPORT    SignalEntry
  311.             WITH    SigGlobals
  312.  
  313.             Head
  314.             MOVE.L    (A7)+,A1                    ;get return address    
  315.             MOVE.L    (A7)+,D0                    ;get message
  316.             BRA.S    SignalEntry
  317.             Tail    'SIGNALME'
  318.  
  319. Signal        PROC    EXPORT                        ;PROCEDURE Signal(code:INTEGER);
  320.             IMPORT    Failure
  321.             EXPORT    SigDeath,SignalEntry
  322. code        EQU        4
  323.             WITH    SigGlobals
  324.  
  325.             Head
  326.             MOVE.L    (A7)+,A1                    ;get return address    
  327.             CLR.L    D0                            ;message := 0
  328. SignalEntry
  329.             MOVE.W    (A7)+,D1                    ;get code
  330.             BNE.S    @0                            ;process the signal if code is non-zero
  331.             JMP    (A1)                            ;return to caller (code was 0)
  332. @0
  333.             MOVE.W    D1,-(A7)                    ;push code
  334.             MOVE.L    D0,-(A7)                    ;push message
  335.             JSR        Failure                        ;this will pop the handler and call SignalFailure
  336. SigDeath
  337.             _Debugger                            ;wasn’t supposed to come back…
  338.             Tail    'SIGNAL  '
  339.  
  340.             ENDP
  341.  
  342.         If  &UsingMacApp Then
  343.             Seg     'MAMain'
  344.         EndIf
  345. DoFailure    PROC    EXPORT                        ;PROCEDURE DoFailure(VAR fi: FailInfo);
  346.             IMPORT    Failure
  347. fi            EQU        4
  348.             
  349.             Head
  350.             BSR        FreeSignal                    ;pop this guy off (but the record is still valid)
  351.             
  352.             MOVE.L    fi(A7),A0                    ;get FailInfo record
  353.             
  354.             MOVEM.L (A0),A2-A7/D3-D7            ;restore regs (can't use A7 anymore)
  355.             ADD     #nSavedRegs*4,A0            ;advance pointer
  356.         
  357.             MOVE.W    (A0)+,D0                     ;get error
  358.         
  359.             TST.W    whatSignals-nSavedRegs*4-2(A0)    ;was CatchSignal used?
  360.             BGT.S    @2                            ;yes, skip
  361.             
  362.             MOVE.L    (A0)+,D1                     ;get message
  363.             MOVEM.L    D0/D1,-(SP)                    ;save error and message for later use
  364.  
  365.             MOVE.W    D0,-(SP)
  366.             MOVE.L    D1,-(SP)                    ;parameters to failure handler
  367.                 
  368.             MOVE.L    (A0)+,D0                    ;check the A6Link
  369.             BEQ.S    @1                            ;if NIL then don't pass it
  370.             MOVE.L    D0,-(SP)                    ;else do pass it
  371. @1
  372.             MOVE.L    (A0)+,A0                    ;get address of failure handler
  373.         
  374.             JSR     (A0)                        ;call failure handler
  375.             
  376.             MOVEM.L    (SP)+,D0/D1                    ;get error & message back
  377.             MOVE.W    D0,-(SP)
  378.             MOVE.L    D1,-(SP)                    ;parameters to Failure
  379.             JSR        Failure
  380.             _Debugger                            ;not supposed to fail to fail
  381.             
  382. @2
  383.             MOVE.W    D0,(A7)                        ;set CatchSignal function result
  384.             MOVE.L    8(A0),A0                    ;address of the failure handler-skip msg. & A6 link
  385.             JMP        (A0)                        ;go to point of CatchSignal
  386.             Tail    'DOFAILUR'
  387.             
  388.             ENDP
  389.                     
  390.  
  391.             END
  392.